﻿using LWH.ByteProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ByteProtocolCSharpDemo
{
    /// <summary>
    /// 创建一个解析协议类，用于解析
    /// 该类一般继承于自定义协议类，但是会对协议类中几个关键的属性进行包装用于解析
    /// </summary>
    class IndefiniteLengthProtocolParser : AbstractIndefiniteLengthProtocol
    {
        /// <summary>
        /// 解析用的长度属性，通过包装协议类中的长度属性得到
        /// 由于长度属性是获取协议总长的关键属性，而长度属性可能会被分割，因此需要进行一个
        /// 包装，在获取长度数据的时候进行判断长度属性数据是否被分割了
        /// </summary>
        ByteBufferParseProperty mParseLengthProperty;
        public IndefiniteLengthProtocolParser()
        {
            mParseLengthProperty = new ByteBufferParseProperty(mBasicStringLengthProperty);

            addProperty(mHeaderProperty);
            addProperty(mParseLengthProperty);
        }

        /// <summary>
        /// 定义协议总长度，用于Factory中进行黏包分包处理，协议也是一个特殊的属性，
        /// 所以可以用解析属性包装一次协议进行解析，在Factory中会看到这个用法
        /// 
        /// 对于固定长度协议，并不需要重写getLength
        /// 

        /// 注意：在解析协议中，如果要获取属性的值（例如这里的getValue），必需要
        /// 确保能获取到值，因为解析协议中，并没有储存任何数据，而
        /// SkeletalProperty.getData和setData是直接控制协议储存的数据，因此在初始
        /// 化协议数据前直接调用而SkeletalProperty的数据方法就会造成错误
        /// 
        /// 在解析协议中的属性如果要获取数据，必需确保重写了getData，并且getData
        /// 的返回不依赖于协议储存的数据
        /// 
        /// 例如：FixedDataProperty和CacheProperty重写了getData，而getData返回的
        /// 是自身属性中储存的一个缓存数组
        /// 
        /// 而在这里ByteBufferParseProperty在tryGetData成功会将数据储存到自身的
        /// 缓存byte数组中，因此只要确保tryGetData返回ture，就可以从缓存数组中获
        /// 取数据
        /// </summary>
        /// <returns></returns>
        public override int getLength()
        {
            return mHeaderProperty.getLength() + mParseLengthProperty.getLength() + new Int32ValueProperty(mParseLengthProperty).getValue();
        }

        #region Getter&Setter
        public ByteBufferParseProperty ParseLengthProperty
        {
            get
            {
                return mParseLengthProperty;
            }
        }
        #endregion
    }
}
